﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.Net.PeerToPeer;
using System.Threading;
using System.Runtime.InteropServices;
using System.IO;
using System.Timers;
using System.Net.Http;
using System.Runtime.InteropServices.ComTypes;

namespace ChatTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            //获取本机的网卡IP
            string name = Dns.GetHostName();
            IPAddress[] ipadrlist = Dns.GetHostAddresses(name);
            foreach (IPAddress ipa in ipadrlist)
            {
                if (ipa.AddressFamily == AddressFamily.InterNetwork)
                {
                    comboBox_IP.Items.Add(ipa.ToString());
                }
            }
            //默认选中最后一个
            if (comboBox_IP.Items.Count > 0)
            {
                comboBox_IP.SelectedIndex = comboBox_IP.Items.Count - 1;
            }
            textBox_Port.Text = new Random().Next(10000, 15000).ToString();
        }
        /// <summary>
        /// 注册聊天室对象
        /// </summary>
        PeerNameRegistration registration;
        private List<Thread> threadList;
        private List<TcpClient> clientList;
        private Thread listenThread;
        private Thread sendAllThread;
        private TcpListener tcpListener;
        private UdpClient sendUserClient;
        private int UserCount = 0;
        private System.Timers.Timer _timer;
        private bool isServer = false;
        private string localInfo = "";
        public void StartSendingBroadMessages()
        {
            _timer = new System.Timers.Timer(5000); // 每5秒执行一次
            _timer.Elapsed += SendBroadMsg;
            _timer.Start();
        }
        private void SendBroadMsg(object sender, ElapsedEventArgs e)
        {
            try
            {
                string onlineUser = "";
                List<string> toAdd = new List<string>();
                List<TcpClient> toRemove = new List<TcpClient>();
                lock (clientList)
                {
                    int i = 0;
                    foreach (TcpClient tcpClient in clientList)
                    {
                        if (tcpClient.Connected)
                        {
                            if (i == 0)
                            {
                                onlineUser = tcpClient.Client.LocalEndPoint.ToString() + "|";
                                i++;
                            }
                            onlineUser += tcpClient.Client.RemoteEndPoint.ToString() + "|";
                            string endpoint = tcpClient.Client.RemoteEndPoint.ToString();
                            if (!listBoxOnline.Items.Cast<string>().Contains(endpoint))
                            {
                                toAdd.Add(endpoint);
                            }
                        }
                        else
                        {
                            toRemove.Add(tcpClient);
                        }
                    }
                }
                // 更新UI
                this.Invoke(new Action(() =>
                {
                    foreach (var endpoint in toAdd)
                    {
                        listBoxOnline.Items.Add(endpoint);
                    }
                    foreach (var tcpClient in toRemove)
                    {
                        string endpoint = tcpClient.Client.RemoteEndPoint.ToString();
                        listBoxOnline.Items.Remove(endpoint);
                        //lbStatus.Items.Add(endpoint + "下线");
                    }
                }));

                // 发送消息
                foreach (TcpClient tcpClient in clientList)
                {
                    if (tcpClient.Connected)
                    {
                        NetworkStream stream = tcpClient.GetStream();
                        StreamWriter sw = new StreamWriter(stream, Encoding.UTF8);
                        string sendStr = "user|" + onlineUser;
                        sw.WriteLine(sendStr);
                        sw.Flush();
                    }
                }
                // 移除断开的连接
                foreach (var tcpClient in toRemove)
                {
                    lock (clientList)
                    {
                        clientList.Remove(tcpClient);
                        tcpClient.Close();
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error: " + ex.Message);
            }
        }
        private void buttonCreate_Click(object sender, EventArgs e)
        {
            if (buttonCreate.Text == "创建聊天室")
            {
                if (tbNewID.Text.Trim().Length > 0)
                {
                    PeerName peerName = new PeerName(tbNewID.Text.Trim(), PeerNameType.Unsecured);
                    registration = new PeerNameRegistration(peerName, int.Parse(textBox_Port.Text));
                    registration.Comment = peerName.ToString();
                    registration.Data = Encoding.UTF8.GetBytes(String.Format("{0}", DateTime.Now.ToString()));
                    registration.Start();
                    tbNewID.ReadOnly = true;
                    buttonCreate.Enabled = false;
                    listBoxOnline.Items.Clear();
                    label_OnlineCount.Text = "在线连接数:1";
                    lbLocal.Text = "本地：" + comboBox_IP.Text + ":" + textBox_Port.Text;
                    listBoxOnline.Items.Add($"{comboBox_IP.Text}:{textBox_Port.Text}");
                    threadList = new List<Thread>();
                    clientList = new List<TcpClient>();
                    try
                    {
                        IPAddress localIP = IPAddress.Parse(comboBox_IP.Text);
                        IPEndPoint localPoint = new IPEndPoint(localIP, int.Parse(textBox_Port.Text));
                        tcpListener = new TcpListener(localPoint);
                        StartSendingBroadMessages();
                        tcpListener.Start(100);
                        listBoxMessage.Items.Clear();
                        listBoxMessage.Items.Add("服务器已启动......");
                        listenThread = new Thread(new ParameterizedThreadStart(AcceptClient));
                        listenThread.IsBackground = true;
                        listenThread.Start(tcpListener);
                        buttonCreate.Enabled = false;
                        buttonSendAll.Enabled = true;
                        buttonSendOne.Enabled = true;
                        isServer = true;
                        localInfo = comboBox_IP.Text + ":" + textBox_Port.Text;
                    }
                    catch (Exception ex) { Console.WriteLine("ERROR5:" + ex.Message); }
                    tbJoinID.Enabled = false;
                    buttonJoin.Enabled = false;
                }
                else
                {
                    MessageBox.Show("请输入聊天室ID！");
                    return;
                }
            }
            else
            {
                tbNewID.Text = "";
                tbNewID.ReadOnly = false;
                registration.Stop();
                buttonCreate.Text = "创建聊天室";
            }
        }
        private void AcceptClient(object obj)
        {
            TcpListener listener = obj as TcpListener;
            try
            {
                while (true)
                {
                    TcpClient tcpClient = listener.AcceptTcpClient();
                    clientList.Add(tcpClient);
                    Thread thread = new Thread(new ParameterizedThreadStart(OperateMsg));
                    thread.IsBackground = true;
                    threadList.Add(thread);
                    thread.Start(tcpClient);
                    this.Invoke(new Action(() =>
                    {
                        listBoxMessage.Items.Add(tcpClient.Client.RemoteEndPoint.ToString() + "登录");
                    }));
                    UserCount++;
                    if (UserCount >= 100)
                    {
                        tcpListener.Stop();
                        break;
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("ERROR3:" + ex.Message);
            }
        }
        private void OperateMsg(object obj)
        {
            TcpClient client = obj as TcpClient;
            Thread receiveMsg = new Thread(new ParameterizedThreadStart(Receive));
            receiveMsg.IsBackground = true;
            receiveMsg.Start(client);

        }
        private void Receive(object obj)
        {
            TcpClient client = obj as TcpClient;
            try
            {
                NetworkStream stream = client.GetStream();
                StreamReader sr = new StreamReader(stream, Encoding.UTF8);
                while (true)
                {
                    string msg = sr.ReadLine();
                    Console.WriteLine("Receive:" + msg);
                    if (!String.IsNullOrEmpty(msg))
                    {
                        string[] info = msg.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
                        if (info[0].Contains("private"))
                        {
                            this.Invoke(new Action(() =>
                            {
                                rbOne.AppendText(info[1] + "说：" + info[2] + " ---" + DateTime.Now.ToString() + "\r\n");
                            }));
                        }
                        else
                        {
                            if (info[0].Contains("client"))
                            {
                                if (info[2] == localInfo)
                                {
                                    this.Invoke(new Action(() =>
                                    {
                                        rbOne.AppendText(info[1] + "说：" + info[3] + " ---" + DateTime.Now.ToString() + "\r\n");
                                    }));
                                }
                                else
                                {
                                    foreach (TcpClient cli in clientList)
                                    {
                                        if (cli.Client.RemoteEndPoint.ToString() == info[2])
                                        {
                                            NetworkStream s = cli.GetStream();
                                            StreamWriter sw = new StreamWriter(s, Encoding.UTF8);
                                            sw.WriteLine(msg);
                                            sw.Flush();
                                        }
                                    }
                                }
                            }
                            else if (info[0].Contains("all"))
                            {
                                this.Invoke(new Action(() =>
                                {
                                    listBoxMessage.Items.Add(info[1] + "说：" + info[2] + " ---" + DateTime.Now.ToString());
                                }));
                                foreach (TcpClient cli in clientList)
                                {
                                    NetworkStream s = cli.GetStream();
                                    StreamWriter sw = new StreamWriter(s, Encoding.UTF8);
                                    sw.WriteLine(msg);
                                    sw.Flush();
                                }
                            }
                        }
                    }
                    else
                    {
                        break;
                    }
                }
                this.Invoke(new Action(() =>
                {
                    listBoxMessage.Items.Add(client.Client.RemoteEndPoint.ToString() + "下线...");
                }));
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error1:" + ex.Message);
            }
        }
        private TcpClient tcpClient;
        private NetworkStream stream;
        private Thread clientReceiveMsgTh;
        private void buttonJoin_Click(object sender, EventArgs e)
        {
            try
            {
                if (buttonJoin.Text == "加入聊天室")
                {
                    if (tbJoinID.Text.Trim().Length == 0)
                    {
                        MessageBox.Show("请输入要加入的聊天室ID！");
                        return;
                    }
                    PeerName shearchPeerName = new PeerName(tbJoinID.Text.Trim(), PeerNameType.Unsecured);
                    PeerNameResolver resolver = new PeerNameResolver();
                    PeerNameRecordCollection peerNameRecords = resolver.Resolve(shearchPeerName);
                    foreach (PeerNameRecord record in peerNameRecords)
                    {
                        foreach (IPEndPoint iep in record.EndPointCollection)
                        {
                            if (iep.AddressFamily == AddressFamily.InterNetwork)
                            {
                                lbStatus.Text = iep.ToString();
                                tbNewID.Enabled = false;
                                buttonCreate.Enabled = false;
                                tbJoinID.Enabled = false;
                                buttonJoin.Enabled = false;
                                try
                                {
                                    string[] remoteInfo = iep.ToString().Split(':');
                                    IPAddress remoteIP = IPAddress.Parse(remoteInfo[0]);
                                    IPEndPoint remotePoint = new IPEndPoint(remoteIP, int.Parse(remoteInfo[1]));
                                    tcpClient = new TcpClient();
                                    tcpClient.Connect(remotePoint);
                                    if (tcpClient.Connected)
                                    {
                                        this.Invoke(new Action(() =>
                                        {
                                            listBoxMessage.Items.Add("连接成功....");
                                        }));
                                        stream = tcpClient.GetStream();
                                        StreamReader sr = new StreamReader(stream, Encoding.UTF8);
                                        StreamWriter sw = new StreamWriter(stream, Encoding.UTF8);
                                        clientReceiveMsgTh = new Thread(new ParameterizedThreadStart(ClientReveiveMsg));
                                        clientReceiveMsgTh.IsBackground = true;
                                        clientReceiveMsgTh.Start(sr);
                                        buttonJoin.Text = "退出聊天室";
                                    }
                                }
                                catch (Exception ex) { MessageBox.Show("服务器连接失败!\r\n" + ex.Message); }
                            }
                        }
                    }
                }
                else
                {
                    listBoxOnline.Items.Clear();
                    buttonJoin.Text = "加入聊天室";
                    listBoxMessage.Items.Add("断开连接....");
                    tcpClient.Close();
                    listBoxOnline.Items.Clear();
                    clientReceiveMsgTh.Abort();

                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
        private void ClientReveiveMsg(object obj)
        {
            StreamReader sr = obj as StreamReader;
            while (true)
            {
                try
                {
                    string str = sr.ReadLine();
                    if (!String.IsNullOrEmpty(str))
                    {
                        string[] info = str.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
                        Console.WriteLine("Received: " + str);  // 添加日志记录

                        if (info.Length > 0)
                        {
                            string u = info[0];
                            if (u.Contains("private"))
                            {
                                this.Invoke(new Action(() =>
                                {
                                    rbOne.AppendText(info[1] + "说：" + info[2] + " ---" + DateTime.Now.ToString() + "\r\n");
                                }));
                            }
                            else if (u.Contains("client"))
                            {
                                this.Invoke(new Action(() =>
                                {
                                    rbOne.AppendText(info[1] + "说：" + info[3] + " --" + DateTime.Now.ToString() + "\r\n");
                                }));
                            }
                            else if (u.Contains("user"))
                            {
                                //lbUser.Items.Clear();  // 注意：这行代码通常不应该在循环中，除非有特定理由
                                foreach (string user in info.Skip(1))  // 跳过第一个元素
                                {
                                    if (!listBoxOnline.Items.Contains(user))
                                    {
                                        this.Invoke(new Action(() => { listBoxOnline.Items.Add(user); }));
                                    }
                                }
                                for (int i = listBoxOnline.Items.Count - 1; i >= 0; i--)
                                {
                                    if (!info.Contains(listBoxOnline.Items[i].ToString()))
                                    {
                                        this.Invoke(new Action(() => { listBoxOnline.Items.Remove(listBoxOnline.Items[i]); }));
                                    }
                                }
                            }
                            else if (u.Contains("all"))
                            {
                                this.Invoke(new Action(() => {
                                    listBoxMessage.Items.Add(info[1] + "说：" + info[2] + " ---" + DateTime.Now.ToString());
                                }));
                            }
                        }
                    }
                    else
                    {
                        this.Invoke((Action)(() => {
                            listBoxMessage.Items.Add("服务器下线");
                            //btnConnet.Enabled = true;
                            //btnDisConnect.Enabled = false;
                            //btnSend.Enabled = false;
                            listBoxOnline.Items.Clear();
                        }));
                        tcpClient.Close();
                        stream.Close();
                        break;
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Error7: " + ex.Message);  // 添加异常处理
                    Thread.CurrentThread.Abort();
                    break;
                }
            }
        }
        private void buttonSendOne_Click(object sender, EventArgs e)
        {
            if (listBoxOnline.SelectedIndex == -1)
            {
                MessageBox.Show("请先选择用户.");
                return;
            }
            if (isServer)
            {
                try
                {
                    string remote = listBoxOnline.SelectedItem.ToString();
                    foreach (TcpClient tcpClient in clientList)
                    {
                        if (tcpClient.Client.RemoteEndPoint.ToString() == remote)
                        {
                            NetworkStream stream = tcpClient.GetStream();
                            StreamWriter sw = new StreamWriter(stream, Encoding.UTF8);
                            string sendInfo = "private|" + tcpClient.Client.LocalEndPoint.ToString() + "|" + tbOne.Text;
                            sw.WriteLine(sendInfo);
                            sw.Flush();
                        }
                    }
                }
                catch (Exception ex) { Console.WriteLine("ERROR6:" + ex.Message); }
            }
            else
            {
                NetworkStream stream = tcpClient.GetStream();
                StreamWriter sw = new StreamWriter(stream, Encoding.UTF8);
                string sendInfo = "client|" + tcpClient.Client.LocalEndPoint.ToString() + "|" + listBoxOnline.SelectedItem.ToString() + "|" + tbOne.Text;
                sw.WriteLine(sendInfo);
                sw.Flush();
            }
        }

        private void buttonSendAll_Click(object sender, EventArgs e)
        {
            if (isServer)
            {
                foreach (TcpClient client in clientList)
                {
                    if (client.Connected)
                    {
                        NetworkStream stream = client.GetStream();
                        StreamWriter sw = new StreamWriter(stream, Encoding.UTF8);
                        sw.WriteLine("all|" + comboBox_IP.Text + ":" + textBox_Port.Text + "|" + textBoxMessage.Text.Trim());
                        sw.Flush();
                    }
                }
                listBoxMessage.Items.Add(comboBox_IP.Text + ":" + textBox_Port.Text + "说：" + textBoxMessage.Text.Trim() + " ---" + DateTime.Now.ToString());
            }
            else
            {
                NetworkStream stream = tcpClient.GetStream();
                StreamWriter sw = new StreamWriter(stream, Encoding.UTF8);
                string sendInfo = "all|" + tcpClient.Client.LocalEndPoint.ToString() + "|" + textBoxMessage.Text.Trim();
                sw.WriteLine(sendInfo);
                sw.Flush();
            }
            textBoxMessage.Text = "";
        }
    }
}
